<?php declare(strict_types=1);
/**
 * @author      xianganyall <xianganyall@gmail.com>
 * @copyright   2023-2025 owner
 **/

namespace Srv\Libs\Pools;

use Srv\Libs\Common\CommJson;
use Srv\Libs\Common\CommTime;
use Srv\Libs\ConfModel\CacheConf;
use Srv\Libs\ConfModel\DbConf;
use Srv\Libs\Exception\MysqlPoolException;
use Srv\Libs\Exception\PoolItemMysqlException;
use Srv\Libs\Exception\PoolItemRedisException;
use Srv\Libs\Exception\RedisPoolException;
use Srv\Libs\Frame\Conf;
use Srv\Libs\Frame\Logs;
use Srv\Libs\Storage\DataMysql;
use Srv\Libs\Storage\DataRedis;

final class Pool
{
    private static bool $initStatus                 = false;        // 初始化状态
    public const POOL_DB                            = 'DB';         // DB连接池类型
    public const POOL_CACHE                         = 'CACHE';      // CACHE连接池类型
    private static array $poolAllList               = [];           // 全部连接池列表
    private static int $loopCheckTime               = 5;            // 循环检查间隔时长[秒]
    private static int $lastCheckTime               = 0;            // 最后检查时间[秒]

    /**
     * @param string $poolType
     * @param string $groupName
     * @return string
     * getIndexKey
     */
    final public static function getIndexKey(string $poolType, string $groupName):string
    {
        return $poolType.'_'.$groupName;
    }

    /**
     * @return bool
     * 获取初始化状态
     */
    final public static function isInit():bool
    {
        return self::$initStatus;
    }

    /**
     * init
     */
    final public static function init():void
    {
        if(self::$initStatus) return;
        self::$initStatus       = true;
        self::$poolAllList      = [];
        // DB连接池
        $DbConfList             = Conf::getDbConfGroup()->getGroupNameList();
        if(count($DbConfList) > 0) foreach($DbConfList as $groupName => $DbConf){
            if(!is_string($groupName) || strlen($groupName) < 1 || !($DbConf instanceof DbConf)) continue;
            $indexKey           = self::getIndexKey(self::POOL_DB, $groupName);
            try{
                $PoolDb         = new PoolDb($DbConf);
                self::$poolAllList[$indexKey] = $PoolDb;
            }catch(MysqlPoolException $MysqlPoolException){
                Logs::exception($MysqlPoolException->getMessageLog(), $MysqlPoolException->getLine(), $MysqlPoolException->getFile(), '');
            }
        }
        // CACHE连接池
        $CacheConfList          = Conf::getCacheConfGroup()->getGroupNameList();
        if(count($CacheConfList) > 0) foreach($CacheConfList as $groupName => $CacheConf){
            if(!is_string($groupName) || strlen($groupName) < 1 || !($CacheConf instanceof CacheConf)) continue;
            $indexKey           = self::getIndexKey(self::POOL_CACHE, $groupName);
            try{
                $PoolCache      = new PoolCache($CacheConf);
                self::$poolAllList[$indexKey] = $PoolCache;
            }catch(RedisPoolException $RedisPoolException){
                Logs::exception($RedisPoolException->getMessageLog(), $RedisPoolException->getLine(), $RedisPoolException->getFile(), '');
            }
        }
    }

    /**
     * @return void
     * loopTimerCheck
     */
    final public static function loopTimerCheck():void
    {
        $currTime               = CommTime::getTimeStamp(0);
        if(self::$loopCheckTime > 0 && ($currTime - self::$lastCheckTime) <= self::$loopCheckTime) return;
        self::$lastCheckTime    = $currTime;
        if(count(self::$poolAllList) > 0) foreach(self::$poolAllList as $poolObject) if($poolObject instanceof PoolAbstract) $poolObject->check();
    }

    /**
     * destroy
     */
    final public static function destroy():void
    {
        if(count(self::$poolAllList) > 0) foreach(self::$poolAllList as $poolObject) if($poolObject instanceof PoolAbstract) unset($poolObject);
        self::$initStatus   = false;
        self::$poolAllList  = [];
    }

    /**
     * @param string $groupName
     * @param bool $isAutoFree
     * @return DataMysql
     * @throws PoolItemMysqlException
     * getDataMysqlByGroup
     */
    final public static function getDataMysqlByGroup(string $groupName, bool $isAutoFree = true):DataMysql
    {
        $indexKey       = self::getIndexKey(self::POOL_DB, $groupName);
        if(isset(self::$poolAllList[$indexKey])){
            $PoolDb     = self::$poolAllList[$indexKey];
            if($PoolDb instanceof PoolDb) return $PoolDb->getDataMysql($isAutoFree);
        }
        throw new PoolItemMysqlException(CommJson::encodeArray(['msg' => 'DataMysql get failed']), -1);
    }

    /**
     * @param string $groupName
     * @param bool $isAutoFree
     * @return DataRedis
     * @throws PoolItemRedisException
     * getDataRedisByGroup
     */
    final public static function getDataRedisByGroup(string $groupName, bool $isAutoFree = true):DataRedis
    {
        $indexKey       = self::getIndexKey(self::POOL_CACHE, $groupName);
        if(isset(self::$poolAllList[$indexKey])){
            $PoolCache  = self::$poolAllList[$indexKey];
            if($PoolCache instanceof PoolCache) return $PoolCache->getDataRedis($isAutoFree);
        }
        throw new PoolItemRedisException(CommJson::encodeArray(['msg' => 'DataRedis get failed']), -1);
    }
}